<?php

class fieldset {
   protected $superclass      = NULL;
   protected $superclass_name = NULL;
   protected $fields          = NULL;
   protected $_data           = NULL;

   public $name   = NULL;
   
   public function  __construct($fieldset_name, $superclass = NULL)
   {
      $this->name   = $fieldset_name;

      if(is_object($superclass))
      {
         $this->superclass       = $superclass;
         $this->superclass_name  = get_class($superclass);

         $this->load();
      }
   }

   private function load()
   {
      if(empty($this->superclass->id))
      {
         return FALSE;
      }
      
      $this->fields = NULL;
      $this->_data  = NULL;
      $FIELDS       = fields::getInstance();
      $DB           = database::getInstance();
      $params       = array();

      if($this->superclass->name == 'article')
      {
         $params['belong'] = 'a';
         $params['node']   = $this->superclass->cat;
      } else
      {
         $params['belong'] = 'c';
         $params['node']   = $this->superclass->id;
      }
      $params['active'] = TRUE;
      $params['fieldset']  = $this->name;

      $fieldset = $FIELDS->splitFields($params);
      foreach($fieldset AS $f)
      {
         $this->fields[(!empty($f->db) ? $f->db : $f->alias)] = $f;
      }

      $DB->sql = 'SELECT * FROM `meccano_'. $this->name .
              '` WHERE `belong` = "'. ($this->superclass->name == 'article' ? 'a' : 'c') .'" '.
              ' AND `node` = '. $this->superclass->id .' ORDER BY `position` ASC';
      $results = $DB->DB_Fetch();
      for($i=0, $t=sizeof($results); $i<$t; $i++)
      {
         $this->addFromSource($results[$i]);
      }
   }


   public function getData()
   {
      return $this->_data;
   }


   protected function addFromSource($data)
   {
      if(empty($data)) return FALSE;
      
      $key = $data['id'];
      $lang = $data['lang'];
      unset($data['id'], $data['lang']);

      if(empty($this->_data[$key]))
      {
         $this->_data[$key] = new fieldsetItem();
         $this->_data[$key]->id = $key;
         $this->_data[$key]->position = $data['position'];
         $this->_data[$key]->belong = $data['belong'];
         $this->_data[$key]->node = $data['node'];
      }


      foreach($data AS $alias_key=>$value)
      {
         if(isset($this->fields[$alias_key]))
         {
            $alias = !empty($this->fields[$alias_key]->db) ? $this->fields[$alias_key]->db : $this->fields[$alias_key]->alias;
            if(!isset($this->_data[$key]->{$alias}))
            {
               $this->_data[$key]->{$alias} = clone $this->fields[$alias_key];
            }

            $this->_data[$key]->{$alias}('self')->normalizeValue($value, $lang);
         }
      }
   }


   public function
   save($data = NULL)
   {
      if(!empty($data))
      {
         $this->prepareInput($data);
      }

      if(!empty($this->_data))
      {
         foreach($this->_data AS $item)
         {
            if($item->deleted == TRUE)
            {
               $this->deleteItem($item);
            } elseif(empty($item->id))
            {
               $this->addItem($item);
            } else
            {
               $this->editItem($item);
            }
         }
      }

      $this->load();
   }


   protected function deleteItem($item)
   {
      $DB = database::getInstance();

      foreach($item AS $i)
      {
         if(is_object($i) && $i->type == 'image')
         {
            $i->validateInput('delete');
         }
      }
      $DB->sql = 'DELETE FROM `meccano_'. $this->name .'` WHERE `id` = "'. $item->id .'"';
      $DB->DB_Query();
      unset($this->_data[$item->id]);
   }


   protected function addItem($item)
   {
      $DB  = database::getInstance();
      $sql = $this->prepareSqlPhrases($item);

      if(!empty($sql))
      {
         $id = $DB->DB_GetNextID('id', 'meccano_'. $this->name);
         foreach($sql AS $query)
         {
            $DB->sql = 'INSERT INTO `meccano_'. $this->name .'` '. $query .', `id` = '. $id .', `cdate` = NOW()';
            $DB->DB_Query();
         }
      }
   }

   protected function editItem($item)
   {
      $DB  = database::getInstance();
      $sql = $this->prepareSqlPhrases($item);

      if(!empty($sql) && !empty($item->id))
      {
         foreach($sql AS $l=>$query)
         {
            $DB->sql = 'UPDATE `meccano_'. $this->name .'` '. $query .' WHERE `lang` = "'. $l .'" AND `id` = '. $item->id;
            $DB->DB_Query();
         }
      }
   }

   private function prepareSqlPhrases($item)
   {
      $sqlp   = array();
      $langs  = request::getLang('all');

      foreach($this->fields AS $f)
      {
         $palias = !empty($f->db) ? $f->db : $f->alias;
         $f = $item->{$palias}('self');

         if(!is_object($f)) continue;
         if(isset($item->{$palias}))
         {
            if($f->translate)
            {
               foreach($langs AS $l)
               {
                  $sqlp[$l['id']][$f->alias] = '`'. (!empty($f->db) ? $f->db : $f->alias) .'` = "'. $f->saveValue($l['id']) .'"';
               }
            } else
            {
               $value = '`'. (!empty($f->db) ? $f->db : $f->alias) .'` = "'. $f->saveValue() .'"';
               foreach($langs AS $l)
               {
                  $sqlp[$l['id']][$f->alias] = $value;
               }
            }
         }
      }

      $sql = array();
      if(!empty($sqlp))
      {
         foreach($langs AS $l)
         {
            $sql[$l['id']]  = ' SET '. implode(', ', $sqlp[$l['id']]);
            $sql[$l['id']] .= ', `lang` = "'. $l['id'] .'"';
            $sql[$l['id']] .= ', `node` = "'. $item->node .'"';
            $sql[$l['id']] .= ', `position` = "'. $item->position .'"';
         }
      }

      return $sql;
   }

   protected function prepareInput($data)
   {
      # PREPARE DATA TO SAVE
      $newdata = array();
      $p = 1;
      if(!empty($this->fields)) foreach ($this->fields AS $f)
      {
         $alias = $f->alias;
         if(!empty($data[$alias]) && is_array($data[$alias]))
         {
            foreach($data[$alias] AS $id=>$value)
            {
               $newdata[$id]['id'] = $id;
               $newdata[$id]['node'] = $this->superclass->id;
               $newdata[$id]['belong'] = $this->superclass_name == 'article' ? 'a' : 'c';
               $newdata[$id][$alias] = $value;

               # SET POSITIONS
               if(!empty($data['position'][$this->name][$id]) && is_numeric($data['position'][$this->name][$id]))
               {
                  $newdata[$id]['position'] = $data['position'][$this->name][$id];
                  $p = $data['position'][$this->name][$id] + 1;
               } else
               {
                  $newdata[$id]['position'] = $p;
                  $p++;
               }
            }
         }
      }
      $data = $newdata;

      # MARK ALL AS DELETED BEFORE WE PROCESS INPUT DATA - TO FILTER DELETED DATA
      if(!empty($this->_data))
      {
         foreach($this->_data AS $k=>$v)
         {
            $this->_data[$k]->deleted = TRUE;
         }
      }


      # UPDATE OBJECT _DATA
      foreach($data AS $key=>$input)
      {
         if(empty($this->_data[$key]))
         {
            $this->_data[$key] = new fieldsetItem();
            $this->_data[$key]->id = NULL;
            $this->_data[$key]->belong = $input['belong'];
            $this->_data[$key]->node = $this->superclass->id;
         } else
         {
            $this->_data[$key]->deleted = FALSE;
         }
         $this->_data[$key]->position = $input['position'];

         foreach($this->fields AS $k=>$f)
         {
            $alias = !empty($f->db) ? $f->db : $f->alias;
            if(!empty($input[$f->alias]))
            {
               if(!isset($this->_data[$key]->{$alias}))
               {
                  $this->_data[$key]->{$alias} = clone $f;
               }

               $this->_data[$key]->{$alias}('self')->validateInput($input[$f->alias], $this->superclass);
            }
         }
      }
   }
}



class fieldsetItem
{
   public $id       = NULL;
   public $position = NULL;
   public $belong   = NULL;
   public $node     = NULL;
   public $deleted  = FALSE;

   private $_data   = NULL;


   function  __construct()
   {
      $this->_data = new stdClass();
   }

   function __call($name, $arguments)
   {
      $arguments = reset($arguments);
      if(isset($this->{$name}))
      {
         if($arguments === 'self')
         {
            return $this->_data->{$name};
         } else
         {
            return $this->_data->{$name}->value($arguments);
         }
      }

      return NULL;
   }

   function __get($name)
   {
      if(isset($this->{$name}))
      {
         $lang = request::getLang('currentId');
         return $this->_data->{$name}->value($lang);
      }

      return NULL;
   }

   public function __set($name, $value)
   {
      $this->_data->{$name} = $value;
   }

   public function __isset($name)
   {
      if(property_exists($this->_data, $name) && is_object($this->_data->{$name}))
         return TRUE;

      return FALSE;
   }
}